/*
 * @Description: 禁飞区
 * @Date: 2022-03-31 16:56:44
 * @Author: yeming
 */
import { transform } from 'ol/proj.js'
import { Circle } from '../model/circle.js'
import { Polygon } from '../model/polygon.js'

class NoFlyZone {
  constructor(ol2d, vectorSource) {
    this.map2d = ol2d.map2d
    this.vectorSource = vectorSource
  }

  /**
   * @desc: 禁飞区渲染(olcs rend3d = true 同步处理，暂不添加3d Entity)
   * @param {Array} list 圆形，多边形禁飞区
   * @return {*}
   * @use: 使用示例
   */
  initAndRenderForbidenArea (list) {
    list.forEach(item => {
      if (item.type == 0) { // 圆形禁飞区
        let latlng = [Number(item.lon1), Number(item.lat1)]
        let circle = new Circle(this.ol2d, this.vectorSource)
        circle.addCircle2(item.id, latlng, 5, 1, item.radius, null, true)
      }
      if (item.type == 1) {
        let latlng = []
        for (let i = 1; i <= 16; i++) {
          let lon = item['lon' + i]
          let lat = item['lat' + i]
          latlng.push([Number(lon), Number(lat)]) // [[lon, lat], [lon, lat], ......, [lon, lat]]
        }
        this.drawPolygonZoneIncoludeSector(item.id, latlng)
      }
    })
  }

  /**
   * 糖果禁飞区（核心：扇形区域）绘制
   * 1、将16个点全部转化为墨卡托投影坐标
   * 2、分别计算处四个扇形转化的墨卡托投影坐标，塞到对应数据集合
   * 3、将墨卡托投影坐标转化为WGS84经纬度坐标
   * 4、绘制处禁飞区
   * 注：
   * latlng 16个点 [[116.2751873879322, 40.04791927304305], ... , [116.4551872, 40.35741]]
   * transform(latlng, 'EPSG:4326', 'EPSG:3857') // WGS84 转 球体墨卡托投影（三维转二维，直角坐标系） ==> 经纬度转投影坐标
   * transform(coordinate, 'EPSG:3857', 'EPSG:4326') // 球体墨卡托投影 转 WGS84（二维转三维） ==> 投影坐标转经纬度
   * id 7 大兴机场半个糖果（需要特殊处理）
   */
  drawPolygonZoneIncoludeSector (id, latlng) {
    let mercator = []; // 传入的16个点转墨卡托投影坐标集合
    latlng.forEach(item => {
      mercator.push(transform(item, 'EPSG:4326', 'EPSG:3857'));
    })
    let allMercatorList = []; // 接收包括原有16个点转墨卡托投影坐标、扇形区域圆弧上的点生成的墨卡托投影坐标
    allMercatorList.push(mercator[0]);
    allMercatorList.push(mercator[1]);
    allMercatorList.push(mercator[2]);

    // 三角函数概览
    // 1、Math.acos(); 反余弦求出cos值
    // 2、2π是用弧度制表示的角。弧度的定义是，弧长/半径，360角是一个圆周，弧长是2πr，则弧度=2πr/r=2π，所以360度就是2π

    // 第一个扇形（三角函数）
    let distance1 = this.getMocatoDistance(mercator[2][1], mercator[2][0], mercator[12][1], mercator[12][0]);
    let c2 = Math.acos((mercator[2][1] - mercator[12][1]) / distance1); // 通过反余弦求出的弧度值
    if (mercator[2][0] - mercator[12][0] < 0) c2 = 2 * Math.PI - c2; // 2π是用弧度制表示的角（此处钝角）
    else if (mercator[2][0] - mercator[12][0] == 0) {
      if (mercator[2][1] - mercator[12][1] > 0) c2 = 0;
      else c2 = Math.PI; // 锐角
    }
    let distance12 = this.getMocatoDistance(mercator[3][1], mercator[3][0], mercator[12][1], mercator[12][0]);
    let b2 = Math.acos((mercator[3][1] - mercator[12][1]) / distance12);
    if (mercator[3][0] - mercator[12][0] < 0) b2 = 2 * Math.PI - b2;
    else if (mercator[3][0] - mercator[12][0] == 0) {
      if (mercator[3][1] - mercator[12][1] > 0) b2 = 0;
      else b2 = Math.PI;
    }
    if (c2 > b2) b2 += 2 * Math.PI;
    for (var i = c2; i < b2;) {
      i += 3 * Math.PI / 180;
      if (i > b2) break;
      let tempLat1 = mercator[12][1] + distance12 * Math.cos(i);
      let tempLng1 = mercator[12][0] + distance12 * Math.sin(i);
      allMercatorList.push([tempLng1, tempLat1]);
    }
    allMercatorList.push(mercator[3]);
    allMercatorList.push(mercator[4]);

    // 第二个扇形
    if (id != 7) { // 大兴机场半个糖果特殊处理
      let distance2 = this.getMocatoDistance(mercator[4][1], mercator[4][0], mercator[13][1], mercator[13][0]);
      let b3 = Math.acos((mercator[4][1] - mercator[13][1]) / distance2);
      if (mercator[4][0] - mercator[13][0] < 0) b3 = 2 * Math.PI - b3;
      else if (mercator[4][0] - mercator[13][0] == 0) {
        if (mercator[4][1] - mercator[13][1] > 0) b3 = 0;
        else b3 = Math.PI;
      }
      let distance22 = this.getMocatoDistance(mercator[5][1], mercator[5][0], mercator[13][1], mercator[13][0]);
      let c3 = Math.acos((mercator[5][1] - mercator[13][1]) / distance22);
      if (mercator[5][0] - mercator[13][0] < 0) c3 = 2 * Math.PI - c3;
      else if (mercator[5][0] - mercator[13][0] == 0) {
        if (mercator[5][1] - mercator[13][1] > 0) c3 = 0;
        else c3 = Math.PI;
      }
      if (b3 > c3) c3 += 2 * Math.PI;
      for (var i = b3; i < c3;) {
        i += 3 * Math.PI / 180;
        if (i > c3) break;
        let tempLat2 = mercator[13][1] + distance22 * Math.cos(i);
        let tempLng2 = mercator[13][0] + distance22 * Math.sin(i);
        allMercatorList.push([tempLng2, tempLat2]);
      }
      allMercatorList.push(mercator[5]);
      allMercatorList.push(mercator[6]);
      allMercatorList.push(mercator[7]);
      allMercatorList.push(mercator[8]);
    }

    // 第三个扇形
    if (id != 7) { // 大兴机场半个糖果特殊处理
      let distance3 = this.getMocatoDistance(mercator[8][1], mercator[8][0], mercator[14][1], mercator[14][0]);
      let c4 = Math.acos((mercator[8][1] - mercator[14][1]) / distance3);
      if (mercator[8][0] - mercator[14][0] < 0) c4 = 2 * Math.PI - c4;
      else if (mercator[8][0] - mercator[14][0] == 0) {
        if (mercator[8][1] - mercator[14][1] > 0) c4 = 0;
        else c4 = Math.PI;
      }
      let distance32 = this.getMocatoDistance(mercator[9][1], mercator[9][0], mercator[14][1], mercator[14][0]);
      let b4 = Math.acos((mercator[9][1] - mercator[14][1]) / distance32);
      if (mercator[9][0] - mercator[14][0] < 0) b4 = 2 * Math.PI - b4;
      else if (mercator[9][0] - mercator[14][0] == 0) {
        if (mercator[9][1] - mercator[14][1] > 0) b4 = 0;
        else b4 = Math.PI;
      }
      if (c4 > b4) b4 += 2 * Math.PI;
      for (var i = c4; i < b4;) {
        i += 3 * Math.PI / 180;
        if (i > b4) break;
        let tempLat3 = mercator[14][1] + distance32 * Math.cos(i);
        let tempLng3 = mercator[14][0] + distance32 * Math.sin(i);
        allMercatorList.push([tempLng3, tempLat3]);
      }
    }
    allMercatorList.push(mercator[9]);
    allMercatorList.push(mercator[10]);

    // 第四个扇形
    let distance4 = this.getMocatoDistance(mercator[10][1], mercator[10][0], mercator[15][1], mercator[15][0]);
    let b1 = Math.acos((mercator[10][1] - mercator[15][1]) / distance4);
    if (mercator[10][0] - mercator[15][0] < 0) b1 = 2 * Math.PI - b1;
    else if (mercator[10][0] - mercator[15][0] == 0) {
      if (mercator[10][1] - mercator[15][1] > 0) b1 = 0;
      else b1 = Math.PI;
    }
    let distance42 = this.getMocatoDistance(mercator[11][1], mercator[11][0], mercator[15][1], mercator[15][0]);
    let c1 = Math.acos((mercator[11][1] - mercator[15][1]) / distance42);
    if (mercator[11][0] - mercator[15][0] < 0) c1 = 2 * Math.PI - c1;
    else if (mercator[11][0] - mercator[15][0] == 0) {
      if (mercator[11][1] - mercator[15][1] > 0) c1 = 0;
      else c1 = Math.PI;
    }
    if (b1 > c1) c1 += 2 * Math.PI;
    for (var i = b1; i < c1;) {
      i += 3 * Math.PI / 180;
      if (i > c1) break;
      let tempLat4 = mercator[15][1] + distance42 * Math.cos(i);
      let tempLng4 = mercator[15][0] + distance42 * Math.sin(i);
      allMercatorList.push([tempLng4, tempLat4]);
    }
    allMercatorList.push(mercator[11]);
    // 所有墨卡托投影坐标集合完结

    let polygon = new Polygon(this.ol2d, this.vectorSource)
    polygon.renderPolygonForbid('forbidPolygon_' + id, [allMercatorList])
  }

  getMocatoDistance = function (sLat, sLon, eLat, eLon) {
    let a = sLat - eLat;
    let b = sLon - eLon;
    let cal2 = Math.pow(a, 2) + Math.pow(b, 2); // Math.pow(底数，几次方)
    let result = Math.sqrt(cal2); // 平方根
    return result;
  }
}

export default NoFlyZone
